package so.sao.shop.supplier.job;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import so.sao.shop.supplier.config.Constant;
import so.sao.shop.supplier.dao.ParameterDao;
import so.sao.shop.supplier.dao.PurchaseItemDao;
import so.sao.shop.supplier.domain.Parameter;
import so.sao.shop.supplier.pojo.Result;
import so.sao.shop.supplier.pojo.vo.OrderRefundLogisticsVo;
import so.sao.shop.supplier.pojo.vo.PurchaseItemVo;
import so.sao.shop.supplier.pojo.vo.PurchaseVo;
import so.sao.shop.supplier.pojo.vo.PurchasesVo;
import so.sao.shop.supplier.service.LogisticsService;
import so.sao.shop.supplier.service.PurchaseItemService;
import so.sao.shop.supplier.service.PurchaseService;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author bzh
 * @date 2017/11/28
 */
@Component
public class AutomaticRefundJob {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * redisTemplate
     */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private PurchaseService purchaseService;
    @Resource
    private LogisticsService logisticsService;
    @Resource
    private PurchaseItemService purchaseItemService;
    @Resource
    private PurchaseItemDao purchaseItemDao;
    @Resource
    private ParameterDao parameterDao;
    @Scheduled(cron = "${jobs.AutomaticRefundJob.automaticRefund}")
    public void automaticRefund() {
        /**
         * 确认退款期限为5天
         * 1.整单退款
         *    a.确认订单状态为退款中；
         *    b.确认该订单已经回寄到货（物流公司：如果运单号没有发生变化，检查物流状态是否为退签<4>，如果发生变化则检查物流状态是否为签收<3>；
         *                         自配送：根据审核通过时间开始倒计时）；
         * 2.部分退款
         *    a.确认订单状态为已收货；
         *    b.确认SKU订单状态为退款中；
         *    c.确认该SKU订单已经回寄到货（物流公司：如果运单号没有发生变化，检查物流状态是否为退签<4>，如果发生变化则检查物流状态是否为签收<3>；
         *                         自配送：根据审核通过时间开始倒计时）；
         */
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(Constant.REDIS_KEY_PREFIX + "AUTOMATIC_REFUND", "1");
        try {
            if (null != lock && lock) {
                //1.查出所有状态为9和12的订单；
                //2.分别存储状态为9的订单和12的订单入list；
                //3.9的订单按整单退款处理
                //4.12的订单按部分退款处理，判断SKU是否有状态为退款中的SKU订单，如果有则走退款，否则不走。
                List<PurchasesVo> purchasesVos = purchaseService.findOrderIdByStatus();
                //存储整单退款的Id
                List<String> refundWholeOrderIds = new ArrayList<>();
                //存储整单自配送订单ID
                List<String> refundWholeArtificialIds = new ArrayList<>();
                //存储整单物流公司配送订单ID
                List<String> refundWholeLogisticsIds = new ArrayList<>();
                //存储整单物流公司配送订单
                List<PurchasesVo> refundWholeLogisticsPurchasesVo = new ArrayList<>();
                //存储部分退款的Id
                List<String> refundSectionOrderIds = new ArrayList<>();
                //存储部分退款自配送订单ID
                List<BigInteger> refundSectionArtificialIds = new ArrayList<>();
                //存储部分退款物流公司配送订单ID
                List<BigInteger> refundSectionLogisticsIds = new ArrayList<>();
                //获取时间段
                List<Parameter> parameters = parameterDao.selectByKey("auto_drawback");
                String days = parameters.get(0).getParameterValue();
                if (purchasesVos.size() > 0) {
                    //拆分整单退款和部分退款的订单ID
                    Map<String, List<String>> map = splitWholeOrSection(purchasesVos);
                    refundWholeOrderIds = map.get("refundWholeOrderIds");
                    refundSectionOrderIds = map.get("refundSectionOrderIds");
                    //拆分整单自配送和物流配送的订单ID
                    Map<String, List<String>> splitWholeMap = splitWholeOrder(refundWholeOrderIds);
                    refundWholeArtificialIds = splitWholeMap.get("refundWholeArtificialIds");
                    refundWholeLogisticsIds = splitWholeMap.get("refundWholeLogisticsIds");
                    //获取物流公司配送的整单退货订单
                    for (PurchasesVo purchasesVo : purchasesVos) {
                        for (String orderId : refundWholeLogisticsIds) {
                            if (Objects.equals(purchasesVo.getOrderId(), orderId)) {
                                refundWholeLogisticsPurchasesVo.add(purchasesVo);
                            }
                        }
                    }
                }

                //1.整单退款——自配送
                if (null != refundWholeArtificialIds && refundWholeArtificialIds.size() > 0) {
                    refundWholeArtificialOrder(refundWholeArtificialIds);
                }
                //2.整单退款——物流配送
                if (refundWholeLogisticsPurchasesVo.size() > 0) {
                    refundWholeLogisticsOrder(refundWholeLogisticsPurchasesVo, refundWholeLogisticsIds,days);
                }
                //部分退款
                //存储部分退货单号的物流信息
                List<OrderRefundLogisticsVo> orderRefundLogisticsVos = new ArrayList<>();
                //存储SKU订单信息列表
                List<PurchaseItemVo> purchaseItemVoList = new ArrayList<>();

                if (refundSectionOrderIds.size() > 0) {
                    /**
                     * 1.获取SKU订单为退款中的订单详情list
                     */
                    //获取详情ID集合
                    purchaseItemVoList = purchaseItemService.getRefundingOrderDetailByOIds(refundSectionOrderIds);
                    List<BigInteger> detailIds = new ArrayList<>();
                    purchaseItemVoList.forEach(purchaseItemVo -> {
                        detailIds.add(purchaseItemVo.getDetailsId());
                    });
                    orderRefundLogisticsVos = purchaseService.getRefundOrderLogistics(null, detailIds);
                    //拆分部分退款自配送和物流配送的SKU订单
                    orderRefundLogisticsVos.forEach(orderRefundLogisticsVo -> {
                        if (Objects.equals(orderRefundLogisticsVo.getLogisticsShipMethod(), 1)) {
                            refundSectionArtificialIds.add(orderRefundLogisticsVo.getDetailsId());
                        } else {
                            refundSectionLogisticsIds.add(orderRefundLogisticsVo.getDetailsId());
                        }
                    });
                }

                //3.部分退款——自配送
                if (refundSectionArtificialIds.size() > 0) {
                    refundSectionArtificialOrder(refundSectionArtificialIds);
                }
                //4.部分退款——物流公司
                if (refundSectionLogisticsIds.size() > 0) {
                    refundSectionLogisticsOrder(refundSectionLogisticsIds, orderRefundLogisticsVos, purchaseItemVoList,days);
                }
                //5.判断订单下是否还有退/换货中的SKU，如果没有则更改订单状态为已完成
                purchaseService.updateRefundOrderStatus(purchasesVos, purchaseItemVoList);
            }
        } catch (Exception e) {
            logger.error("系统异常", e);
        } finally {
            if (null != lock && lock) {
                redisTemplate.delete(Constant.REDIS_KEY_PREFIX + "AUTOMATIC_REFUND");
            }
        }
    }

    /**
     * 拆分整单自配送和物流配送的订单ID
     *
     * @param refundWholeOrderIds 整单退款订单ID集合
     */
    private Map<String, List<String>> splitWholeOrder(List<String> refundWholeOrderIds) {
        List<String> refundWholeArtificialIds = new ArrayList<>();
        List<String> refundWholeLogisticsIds = new ArrayList<>();
        if (refundWholeOrderIds.size() > 0) {
            List<OrderRefundLogisticsVo> orderRefundLogisticsVos = purchaseService.getRefundOrderLogistics(refundWholeOrderIds, null);
            orderRefundLogisticsVos.forEach(orderRefundLogisticsVo -> {
                if (Objects.equals(orderRefundLogisticsVo.getLogisticsShipMethod(), 1)) {
                    refundWholeArtificialIds.add(orderRefundLogisticsVo.getOrderId());
                } else {
                    refundWholeLogisticsIds.add(orderRefundLogisticsVo.getOrderId());
                }
            });
        }
        Map<String, List<String>> map = new HashMap<>();
        map.put("refundWholeArtificialIds", refundWholeArtificialIds);
        map.put("refundWholeLogisticsIds", refundWholeLogisticsIds);
        return map;
    }

    /**
     * 拆分整单退款和部分退款的订单ID
     *
     * @param purchasesVos 订单列表
     */
    private Map<String, List<String>> splitWholeOrSection(List<PurchasesVo> purchasesVos) {
        List<String> refundWholeOrderIds = new ArrayList<>();
        List<String> refundSectionOrderIds = new ArrayList<>();
        purchasesVos.forEach(purchasesVo -> {
            if (Objects.equals(Integer.valueOf(purchasesVo.getOrderStatus()), Constant.OrderStatusConfig.REFUNDING)) {
                refundWholeOrderIds.add(purchasesVo.getOrderId());
            } else {
                refundSectionOrderIds.add(purchasesVo.getOrderId());
            }
        });
        Map<String, List<String>> map = new HashMap<>();
        map.put("refundWholeOrderIds", refundWholeOrderIds);
        map.put("refundSectionOrderIds", refundSectionOrderIds);
        return map;
    }

    /**
     * 1.整单退款自动任务
     * 自配送
     *
     * @param refundWholeArtificialIds
     * @throws Exception
     */
    private void refundWholeArtificialOrder(List<String> refundWholeArtificialIds) throws Exception {
        //过滤退款审核时间大于当前时间5天的订单
        List<String> orderIds = purchaseService.getOrderIdByTime(refundWholeArtificialIds);
        if (orderIds.size() > 0) {
            for (String orderId : orderIds) {
                purchaseService.refundByOrderId(orderId);
            }
        }
    }

    /**
     * 2.整单退款自动任务
     * 物流配送
     *
     * @param refundWholeLogisticsPurchasesVo 物流配送的订单
     * @throws Exception
     */
    private void refundWholeLogisticsOrder(List<PurchasesVo> refundWholeLogisticsPurchasesVo, List<String> refundWholeLogisticsIds,String days) throws Exception {
        /**
         * 如果物流公司单号与原发货物流单号一致，判断state == 4;
         * 如果物流公司单号与原发货物流单号不一致，判断stats == 3.
         */
        //存储退款ID集合
        List<String> orderIds = new ArrayList<>();
        //获取回寄订单物流信息
        List<OrderRefundLogisticsVo> orderRefundLogisticsVos = purchaseService.getRefundOrderLogistics(refundWholeLogisticsIds, null);
        for (PurchasesVo purchasesVo : refundWholeLogisticsPurchasesVo) {
            for (OrderRefundLogisticsVo orderRefundLogisticsVo : orderRefundLogisticsVos) {
                if (purchasesVo.getOrderShipmentNumber().equals(orderRefundLogisticsVo.getLogisticsShipmentNumber())) {
                    Result result = logisticsService.findLogisticInfo(purchasesVo.getOrderShipmentNumber());
                    JSONObject jsonObject = JSONObject.fromObject(result.getData());
                    if (null == jsonObject && jsonObject.size() == 0) {
                        continue;
                    }
                    if (null != jsonObject && jsonObject.size() > 0) {
                        String state = String.valueOf(jsonObject.get("state"));
                        if (Objects.equals(state, "4")) {
                            //计算时间差
                            if (compareDate(jsonObject,days)) {
                                orderIds.add(purchasesVo.getOrderId());
                            }
                        }
                    }
                } else {
                    Result result = logisticsService.findLogisticInfo(purchasesVo.getOrderShipmentNumber());
                    JSONObject jsonObject = JSONObject.fromObject(result.getData());
                    if (null != jsonObject && jsonObject.size() > 0) {
                        String state = String.valueOf(jsonObject.get("state"));
                        if (Objects.equals(state, "3")) {
                            //计算时间差
                            if (compareDate(jsonObject,days)) {
                                orderIds.add(purchasesVo.getOrderId());
                            }
                        }
                    }
                }
            }

        }
        //调用退款
        for (String orderId : orderIds) {
            purchaseService.refundByOrderId(orderId);
        }
    }

    /**
     * 3.部分退款——自配送
     *
     * @param refundSectionArtificialIds 部分退款自配送详情ID集合
     * @throws Exception
     */
    private void refundSectionArtificialOrder(List<BigInteger> refundSectionArtificialIds) throws Exception {
        //获取审核通过大于5天的SUK退/换货单号
        List<String> returnNums = purchaseItemDao.getReturnNumByDetailIds(refundSectionArtificialIds, new Date());
        if (returnNums.size() > 0) {
            for (String returnNum : returnNums) {
                purchaseService.refundByOrderId(returnNum);
            }
        }
    }

    /**
     * 4.部分退款——物流公司
     *
     * @param refundSectionLogisticsIds 部分退款物流公司订单详情ID
     * @param orderRefundLogisticsVos   物流配送的SKU订单列表
     * @param purchaseItemVoList        订单详情列表
     * @throws Exception
     */
    private void refundSectionLogisticsOrder(List<BigInteger> refundSectionLogisticsIds,
                                             List<OrderRefundLogisticsVo> orderRefundLogisticsVos,
                                             List<PurchaseItemVo> purchaseItemVoList,
                                             String days) throws Exception {
        //存储物流配送的可退货的SKU订单详情
        List<PurchaseItemVo> refundSectionLogisticsPurchase = new ArrayList<>();
        //存储部分物流公司配送退/换货单号
        List<String> refundSectionLogisticsReturnNums = new ArrayList<>();
        for (PurchaseItemVo purchaseItemVo : purchaseItemVoList) {
            for (BigInteger detailId : refundSectionLogisticsIds) {
                if (Objects.equals(purchaseItemVo.getDetailsId(), detailId)) {
                    refundSectionLogisticsPurchase.add(purchaseItemVo);
                }
            }
        }
        if (null != refundSectionLogisticsIds && refundSectionLogisticsIds.size() > 0) {
            //部分退款获取物流公司的物流单号
            for (PurchaseItemVo purchaseItemVo : refundSectionLogisticsPurchase) {
                for (OrderRefundLogisticsVo orderRefundLogisticsVo : orderRefundLogisticsVos) {
                    if (Objects.equals(orderRefundLogisticsVo.getDetailsId(), purchaseItemVo.getDetailsId())) {
                        Result result = logisticsService.findLogisticInfo(orderRefundLogisticsVo.getLogisticsShipmentNumber());
                        JSONObject jsonObject = JSONObject.fromObject(result.getData());
                        if (null == jsonObject || jsonObject.size() == 0) {
                            continue;
                        }
                        String state = String.valueOf(jsonObject.get("state"));
                        if (Objects.equals(state, "3")) {
                            //计算时间差
                            if (compareDate(jsonObject,days)) {
                                refundSectionLogisticsReturnNums.add(purchaseItemVo.getReturnNumber());
                            }
                        }

                    }
                }
            }
        }
        //调用退款
        for (String orderId : refundSectionLogisticsReturnNums) {
            purchaseService.refundByOrderId(orderId);
        }
    }

    //计算时间差
    private boolean compareDate(JSONObject jsonObject,String days) throws ParseException {
        //获取物流跟踪信息
        Object followInfo = jsonObject.get("data");
        JSONArray jsonArray = JSONArray.fromObject(followInfo);
        //获取最近物流信息
        Object lastFollowInfo = jsonArray.get(0);
        //把最近物流信息JSON化
        JSONObject jsonObjectReceiveDate = JSONObject.fromObject(lastFollowInfo);
        String followTime = String.valueOf(jsonObjectReceiveDate.get("time"));
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date receiveT = simpleDateFormat.parse(followTime);
        Long timeDiff = System.currentTimeMillis() - receiveT.getTime();
        Long hours = timeDiff / (3600 * 1000);
        if (hours >= (Integer.valueOf(days)*24-1)) {
            return true;
        }
        return false;
    }
}
